package net.net23.sysdent.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import net.net23.sysdent.WindowUtility;
import net.net23.sysdent.handlers.KeyHandler;
import net.net23.sysdent.sql.DBEngine;
import net.net23.sysdent.sql.DBSet;
import net.net23.sysdent.sql.exception.DataBaseConnectionException;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;

public class JDBCExplorerUi extends JFrame {

	private static final long serialVersionUID = -8128629839565369827L;

	private JPanel north;
	private JToolBar toolBar;
	private JButton connect;
	private JButton run;
	private JButton runPage;
	private JButton save;

	private JPanel center;
	private RSyntaxTextArea query;
	private JScrollPane scroll;
	private JResult result;
	private JTextField status;
	int page = 1;
	String prevQuery = null;

	private JDBCEXplorerAutocompleteComponent autocompleteComponent;

	public JDBCExplorerUi() throws FileNotFoundException, IOException {
		initialize();
		createNorth();
		createCenter();
		createSouth();
		setVisible(true);
	}

	private void initialize() {
		setLayout(new BorderLayout());
		setTitle(getClass().getName());
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		WindowUtility.center(this, 640, 480);
	}

	private void createNorth() {
		north = new JPanel(new BorderLayout());
		toolBar = new JToolBar();

		connect = new JButton(new ImageIcon("icons/connect.png"));
		connect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doConnect();
			}
		});
		toolBar.add(connect);

		run = new JButton(new ImageIcon("icons/run.png"));
		run.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doExecuteQuery();
			}
		});
		toolBar.add(run);

		runPage = new JButton(new ImageIcon("icons/run.png"));
		runPage.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doExecuteQuery(0, 10);
			}
		});
		toolBar.add(runPage);

		save = new JButton(new ImageIcon("icons/save.png"));
		save.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				doSaveResult();
			}
		});
		toolBar.add(save);

		north.add(toolBar, BorderLayout.NORTH);
		add(north, BorderLayout.NORTH);
	}

	private void createCenter() {
		center = new JPanel(new BorderLayout());
		query = new RSyntaxTextArea();
		add(new RTextScrollPane(query));
		query.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
		query.setRows(5);
		query.addKeyListener(new KeyHandler() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_F9) {
					doExecuteQuery(0, 10);
				}
			}
		});
		autocompleteComponent = new JDBCEXplorerAutocompleteComponent(query);

		result = new JResult();
		scroll = new JScrollPane(result);
		JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, query,
				scroll);
		split.setDividerLocation(85);
		center.add(split, BorderLayout.CENTER);
		add(center, BorderLayout.CENTER);
	}

	private void createSouth() {
		status = new JTextField();
		status.setEditable(false);
		add(status, BorderLayout.SOUTH);
	}

	public static void main(String[] args) throws FileNotFoundException,
			IOException {
		try {
			UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		new JDBCExplorerUi();
	}

	private void doExecuteQuery() {
		doExecuteQuery(0, 0);
	}

	private void doExecuteQuery(int offset, int size) {
		String _query = query.getSelectedText();
		if (_query == null || _query.length() == 0) {
			_query = query.getText();
		}
		if (_query.length() > 0) {
			try {
				long initTime = System.currentTimeMillis();
				if (prevQuery != null && !prevQuery.equals(_query)) {
					page = 1;
				}
				int end = offset + (page * size);
				prevQuery = _query;
				if (end > 0) {
					_query = "select * from ( select t.* from ( "
							+ _query + " ) t where rownum <= " + end
							+ " ) where rownum >= " + offset;
					page++;
				}
				result.updateModel(executeQuery(_query));
				long endTime = System.currentTimeMillis();
				status.setForeground(Color.BLACK);
				status.setText("Consulta ejecutada en: " + (endTime - initTime)
						+ " milisegundos.");
			} catch (Exception e) {
				status.setForeground(Color.RED);
				status.setText(e.getMessage());
				e.printStackTrace();
			}
		}
	}

	private void doSaveResult() {
		JFileChooser chooser = new JFileChooser();
		int opt = chooser.showSaveDialog(this);
		if (opt == JFileChooser.APPROVE_OPTION) {
			File selectedFile = chooser.getSelectedFile();
			String separator = JOptionPane.showInputDialog(this,
					"Ingrese el separador de columnas", ",");
			if (separator != null) {
				try {
					result.saveResult(selectedFile, separator);
					JOptionPane.showMessageDialog(this, "Archivo guardado en: "
							+ selectedFile.getAbsolutePath());
				} catch (IOException e) {
					status.setText(e.getMessage());
					e.printStackTrace();
				}
			}
		}

	}

	private void doConnect() {
		new ConnectionDialog(autocompleteComponent);
	}

	// ////////////////////////////////////

	private DBSet executeQuery(String _query) throws SQLException, DataBaseConnectionException {
		return DBEngine.executeQuery(_query);
	}
}
